﻿using Newtonsoft.Json.Linq;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Net;
using System.Text.RegularExpressions;
using System.Threading;
using System.Threading.Tasks;

namespace Onetube.Providers.Extensions
{
    public static class ExtentionMethods
    {
        private static DateTime _epochDate = new DateTime(1970, 1, 1, 0, 0, 0, DateTimeKind.Utc);

        static ExtentionMethods()
        {
        }

        public static string Slice(this string source, int start, int end)
        {
            if (end < 0)
                end = source.Length + end;
            int length = end - start;
            return source.Substring(start, length);
        }

        public static string ReversedSubString(this string value, int start, int end)
        {
            if (string.IsNullOrEmpty(value))
                return string.Empty;
            else
                return new string(Enumerable.ToArray<char>(Enumerable.Reverse<char>((IEnumerable<char>)value.Substring(start + 1, end - start).ToCharArray())));
        }

        public static string Truncate(this string value, int maxLength)
        {
            if (string.IsNullOrEmpty(value))
                return string.Empty;
            if (value.Length > maxLength)
                return value.Substring(0, maxLength);
            else
                return value;
        }

        public static string RemoveSpecialCharacters(this string inputString)
        {
            if (string.IsNullOrEmpty(inputString))
                return string.Empty;
            else
                return inputString.Replace("\\", "");
        }

        public static string RemoveAllSpecialCharacters(this string inputString)
        {
            if (string.IsNullOrEmpty(inputString))
                return string.Empty;
            else
                return new Regex("(?:[^a-z0-9 ]|(?<=['\"])s)", RegexOptions.CultureInvariant | RegexOptions.IgnoreCase).Replace(inputString, string.Empty);
        }

        public static double ToEpocSeconds(this DateTime dateTime)
        {
            return (dateTime.ToUniversalTime() - ExtentionMethods._epochDate).TotalSeconds;
        }

        public static DateTime EpocToDateTime(this double seconds)
        {
            return ExtentionMethods._epochDate.ToUniversalTime().AddSeconds(seconds);
        }

        public static string ByteToString(this byte[] buffer)
        {
            string str = "";
            for (int index = 0; index < buffer.Length; ++index)
                str = str + buffer[index].ToString("X2");
            return str;
        }

        public static JToken SelectToken(this JToken token, string key)
        {
            if (token == null || string.IsNullOrEmpty(key))
                return (JToken)null;
            string str1 = key;
            string[] separator = new string[1]
            {
                "."
            };
            int num = 0;
            foreach (string str2 in str1.Split(separator, (StringSplitOptions)num))
                token = token[(object)key];
            return token;
        }

        public static string JsonValueToString(this JToken token)
        {
            if (token != null)
                return (string)token;
            else
                return string.Empty;
        }

        public static bool JsonValueToBool(this JToken token)
        {
            if (token != null)
                return (bool)token;
            else
                return false;
        }

        public static int JsonValueToInt(this JToken token)
        {
            if (token != null)
                return (int)token;
            else
                return 0;
        }

        public static long JsonValueToLong(this JToken token)
        {
            if (token != null)
                return (long)token;
            else
                return 0L;
        }

        public static double JsonValueToDouble(this JToken token)
        {
            if (token != null)
                return (double)token;
            else
                return 0.0;
        }

        public static DateTime JsonValueToDateTime(this JToken token)
        {
            if (token != null)
                return (DateTime)token;
            else
                return DateTime.MinValue;
        }

        public static string JsonValueToEncoding(this JToken token)
        {
            if (token != null)
                return ExtentionMethods.JsonValueToString(token.SelectToken("url"));
            else
                return (string)null;
        }

        public static string ToTitleCase(this string str)
        {
            string str1 = str;
            if (!string.IsNullOrEmpty(str))
            {
                string[] strArray = str.Split(new char[1]
                {
                    ' '
                });
                for (int index = 0; index < strArray.Length; ++index)
                {
                    string str2 = strArray[index];
                    if (str2.Length > 0)
                        strArray[index] = str2[0].ToString().ToUpper() + str2.Substring(1);
                }
                str1 = string.Join(" ", strArray);
            }
            return str1;
        }

        public static Dictionary<string, string> ParseQueryString(this string s)
        {
            Dictionary<string, string> dictionary = new Dictionary<string, string>();
            if (s.Contains("?"))
                s = s.Substring(s.IndexOf('?') + 1);
            foreach (string input in Regex.Split(s, "&"))
            {
                string[] strArray = Regex.Split(input, "=");
                if (strArray.Length == 2)
                    dictionary.Add(strArray[0], strArray[1]);
                else
                    dictionary.Add(strArray[0], string.Empty);
            }
            return dictionary;
        }

       public static async Task<HttpWebResponse> GetResponseAsync(this HttpWebRequest request, CancellationToken ct)
            {
                using (ct.Register(() => request.Abort(), useSynchronizationContext: false))
                {
                    try
                    {
                        var response = await request.GetResponseAsync().ConfigureAwait(false);
                        ct.ThrowIfCancellationRequested();
                        return (HttpWebResponse)response;
                    }
                    catch (WebException ex)
                    {
                        // WebException is thrown when request.Abort() is called,
                        // but there may be many other reasons,
                        // propagate the WebException to the caller correctly
                        if (ct.IsCancellationRequested)
                        {
                            // the WebException will be available as Exception.InnerException
                            throw new OperationCanceledException(ex.Message, ex, ct);
                        }

                        // cancellation hasn't been requested, rethrow the original WebException
                        throw;
                    }
                }
            }
    }
}